package shell

import (
	"encoding/json"
	"log/lg"
	"log/nsq"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

// GoPs 当个服务当前的状态, 进程号,服务名,运行路径,cpu使用,内存使用
type GoPs struct {
	Pid        string    `json:"pid"`
	Servername string    `json:"servername"`
	Path       string    `json:"path"`
	Cpu        float64   `json:"cpu,number"`
	Memory     float64   `json:"memory,number"`
	Date       time.Time `json:"date"`
}

//定义对象结构体
type bash struct {
	shell string
}

//初始化全局数据采集json结构体
var g = &GoPs{}

// NewGoPs 构造结构体函数,数据初始化
func NewGoPs(shell string) (bs *bash) {
	//初始化结构体
	bs = &bash{shell: shell}

	//采集数据方法
	go bs.collection()

	return
}

//获取单个进程的cpu,内存数据方法
func (b *bash) process() {
	c := exec.Command("bash", "-c", b.shell+" "+g.Pid+" |awk 'NR==4||NR==3{print $NF}'|sed 's/%//g'")
	date, err := c.CombinedOutput()
	if err != nil {
		lg.Log.Error(err)
	}
	//字符串转成fliat64
	v := strings.Split(string(date), "\n")
	b1, err := strconv.ParseFloat(v[1], 64)
	if err != nil {
		lg.Log.Panic("自字符转float64失败", err)
	}
	b0, err := strconv.ParseFloat(v[0], 64)
	if err != nil {
		lg.Log.Panic("自字符转float64失败", err)
	}
	//添加百分小数 es数据库需要
	g.Cpu = b1 * 0.01
	g.Memory = b0 * 0.01
}

//数据采集
func (b *bash) collection() {

	for {
		//每5秒进行数据采集
		time.Sleep(time.Second * 5)

		//传入执行的shell
		c := exec.Command("bash", "-c", b.shell)
		d, err := c.CombinedOutput()
		if err != nil {
			lg.Log.Error(err)
			return
		}

		//切割获取的数据，把获取到底字节转换成字符串，按照换行符号进行切割
		for _, v := range strings.Split(string(d), "\n") {
			//判断获取的数据大小，长度大于1进行数据采集
			if len(v) > 1 {

				gp := strings.Fields(v)
				//过滤出不需要的关键字服务,跳出本次采集
				if gp[2] == "gops" {
					continue
				}
				g = &GoPs{
					Pid:        gp[0],
					Servername: gp[2],
					Path:       gp[len(gp)-1],
					Date:       time.Now(),
				}
				//执行采集cpu，内存方法进行采集
				b.process()
				//解析字符串打印日志
				b, err := json.Marshal(&g)
				if err != nil {
					lg.Log.Panic("数据解析json错误：", err)
				}
				//发送到nsq
				nsq.SendGoPs(b)

				lg.Log.Info("gops数据采集成功!!!", string(b))

			}
		}
	}
}
